All files / src/app/recipes/[id]/hooks useRecipeDetail.ts

0% Statements 0/29
0% Branches 0/10
0% Functions 0/10
0% Lines 0/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81                                                                                                                                                                 
import { useQuery } from '@apollo/client/react';
import { useSession } from 'next-auth/react';
import { useCallback, useMemo, useState } from 'react';
import { GET_RECIPE_BY_ID } from '@/lib/graphql/queries';
import type { RecipeDetailData } from '../types';
import { extractYoutubeId, sortByOrder } from '../utils';
 
const SERVING_MIN = 1;
const SERVING_MAX = 20;
 
export const useRecipeDetail = (recipeId: string) => {
  const { data: session } = useSession();
  const { data, loading, error } = useQuery<RecipeDetailData>(
    GET_RECIPE_BY_ID,
    { variables: { id: recipeId } },
  );
 
  const recipe = data?.getRecipeById;
 
  /* ── Serving adjuster ── */
  const [servingMultiplier, setServingMultiplier] = useState(1);
 
  const adjustedServings = useMemo(
    () => (recipe ? recipe.servings * servingMultiplier : 0),
    [recipe, servingMultiplier],
  );
 
  const incrementServings = useCallback(
    () => setServingMultiplier((m) => Math.min(m + 1, SERVING_MAX)),
    [],
  );
  const decrementServings = useCallback(
    () => setServingMultiplier((m) => Math.max(m - 1, SERVING_MIN)),
    [],
  );
 
  /* ── Checked ingredients ── */
  const [checkedIngredients, setCheckedIngredients] = useState<Set<string>>(
    new Set(),
  );
 
  const toggleIngredient = useCallback((localId: string) => {
    setCheckedIngredients((prev) => {
      const next = new Set(prev);
      if (next.has(localId)) next.delete(localId);
      else next.add(localId);
      return next;
    });
  }, []);
 
  /* ── Derived data ── */
  const youtubeId = useMemo(
    () => (recipe?.youtubeLink ? extractYoutubeId(recipe.youtubeLink) : null),
    [recipe?.youtubeLink],
  );
 
  const isOwner =
    !!recipe &&
    (session?.user as { id?: string } | undefined)?.id === recipe.createdBy;
 
  const sortedSteps = useMemo(
    () => (recipe ? sortByOrder(recipe.preparationSteps) : []),
    [recipe],
  );
 
  return {
    recipe,
    loading,
    error,
    servingMultiplier,
    adjustedServings,
    checkedIngredients,
    toggleIngredient,
    incrementServings,
    decrementServings,
    youtubeId,
    isOwner,
    sortedSteps,
  };
};